//
//  NetworkManager.swift
//  Urso
//
//  Created by Cosmetic Cygia on 2024/6/12.
//

import Foundation
import AppKit



func sendString(host: String, port: Int, stringToSend: String, timeout: Double) -> String {
    var responseString = ""
    
    let stream = URLSession.shared.streamTask(withHostName: host, port: port)
    
    // stream.startSecureConnection() // Start secure connection if necessary
    stream.write(stringToSend.data(using: .utf8)!, timeout: timeout) { error in
        if let error = error {
            ELog.e( #function, "Error writing to stream: \(error)", #line)
            PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error writing to stream: \(error)")
        } else {
            stream.readData(ofMinLength: 0, maxLength: 4096, timeout: timeout) { data, eof, error in
                if let error = error {
                    ELog.e( #function, "Error reading from stream: \(error)", #line)
                    PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error reading from stream: \(error)")
                } else if let data = data {
                    responseString = String(data: data, encoding: .utf8) ?? ""
                }
            }
        }
    }
    stream.resume()
    return responseString
}

func deprecateStreamRead(stream: URLSessionStreamTask) {
    
    stream.readData(ofMinLength: 0, maxLength: 1024, timeout: 0 ) { data, eof, error in
    }
    
    stream.resume()
}

func sendString(stream: URLSessionStreamTask, stringToSend: String, timeout: Double, escape: ((_ isSuccess: Bool, _ response: String) -> Void)?) {
    let byteArray: [UInt8] = Array(stringToSend.utf8)
    
    sendUInt8(stream: stream, dataToSend: byteArray, timeout: timeout, escape: { isSuccess, response in
        if (isSuccess) {
            if let str = String(bytes: response, encoding: .utf8) {
                escape!(true, str)
            } else {
                escape!(true, "")
            }
        } else {
            escape!(false, String(bytes:  response, encoding: .utf8) ?? "")
        }
    })
}

func sendUInt8(stream: URLSessionStreamTask, dataToSend: [UInt8], timeout: Double, escape: ((_ isSuccess: Bool, _ response: [UInt8]) -> Void)?) {
    
    print(Thread.current.hashValue)
    let data = Data(dataToSend)
    stream.write(data, timeout: timeout) { error in
        if let error = error {
            ELog.d(#function, "Error writing to stream: \(error)", #line)
            PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error writing to stream: \(error)")
            escape!(false, [UInt8](error.localizedDescription.utf8))
            } else {
            stream.readData(ofMinLength: 0, maxLength: 1024, timeout: timeout ) { data, eof, error in
                if let error = error {
                    ELog.e( #function, "Error reading from stream: \(error)", #line)
                    PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error reading from stream: \(error)")
                    escape!(false, [UInt8](error.localizedDescription.utf8))
                } else if let receivedData = data {
                    ELog.d(#function, [UInt8](receivedData).description, #line)
                    
                    let response = [UInt8](receivedData)
                    
                    //     stream.closeWrite()
                    escape!(true, response)
                 }
            }
        }
    }
    stream.resume()
}

func sendUInt8Sync(stream: URLSessionStreamTask, dataToSend: [UInt8], timeout: Double, escape: ((_ isSuccess: Bool, _ response: [UInt8]) -> Void)?) {
    let data = Data(dataToSend)
    let semaphore = DispatchSemaphore(value: 0)  // Semaphore to block the current thread
    
    // Write the data to the stream
    stream.write(data, timeout: timeout) { error in
        if let error = error {
            ELog.d(#function, "Error writing to stream: \(error)", #line)
            PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error writing to stream: \(error)")
            escape!(false, [UInt8](error.localizedDescription.utf8))
            semaphore.signal() // Release semaphore to avoid deadlock
        } else {
            // Read the data from the stream synchronously
            stream.readData(ofMinLength: 0, maxLength: 1024, timeout: timeout) { data, eof, error in
                if let error = error {
                    ELog.e(#function, "Error reading from stream: \(error)", #line)
                    PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error reading from stream: \(error)")
                    escape!(false, [UInt8](error.localizedDescription.utf8))
                    semaphore.signal() // Release semaphore to avoid deadlock
                } else if let receivedData = data {
                    ELog.d(#function, [UInt8](receivedData).description, #line)
                    
                    let response = [UInt8](receivedData)
                    escape!(true, response)
                    semaphore.signal() // Release semaphore to avoid deadlock
                }
            }
        }
    }
    
    stream.resume()
    
    // Wait for the semaphore to signal that the read operation has completed
    _ = semaphore.wait(timeout: .now() + timeout) // You can set your own timeout here
}





func postString(url: String, stringToPost: String, timeout: Double) -> String {
    let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
    
    request.httpMethod = "POST"
    let postString = stringToPost
    request.httpBody = postString.data(using: String.Encoding.utf8)
    
    var responseString = ""
    
    let semaphore = DispatchSemaphore(value: 0)
    
    let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
        guard let data = data, error == nil else {
            ELog.e(#function, "Error: \(error?.localizedDescription ?? "Unknown error")", #line)
            PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Error: \(error?.localizedDescription ?? "Unknown error")")
            semaphore.signal()
            return
        }
        
        if let httpResponse = response as? HTTPURLResponse {
            if httpResponse.statusCode == 200 {
                responseString = String(data: data, encoding: .utf8) ?? ""
            } else {
                ELog.e(#function, "HTTP response status code: \(httpResponse.statusCode)", #line)
                PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "HTTP response status code: \(httpResponse.statusCode)")
            }
        }
        
        semaphore.signal()
    }
    
    task.resume()
    
    _ = semaphore.wait(timeout: DispatchTime.now() + timeout)
    
    return responseString
}

func postImageToURL(image: NSImage, uuid: String, result: String, url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
    guard let imageData = image.tiffRepresentation else {
        ELog.e(#function, "Failed to convert image to data.", #line)
        PavaoManager.instance.saveLog(logLevel: LOG_LEVEL.error, logContent: "Failed to convert image to data.")
        return
    }
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("uuid", forHTTPHeaderField: uuid)
    request.addValue("result", forHTTPHeaderField: result)
    request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
    request.httpBody = imageData
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        completion(data, response, error)
    }
    task.resume()
}
